package com.qf.producer;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitOperations;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.amqp.RabbitTemplateConfigurer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.context.annotation.Bean;


// Generated by https://start.springboot.io
// 优质的 spring/boot/data/security/cloud 框架中文文档尽在 => https://springdoc.cn
@SpringBootApplication
public class ProducerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProducerApplication.class, args);
    }


    @Bean
    public RabbitTemplate rabbitTemplate(RabbitTemplateConfigurer configurer, ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate();
        configurer.configure(rabbitTemplate, connectionFactory);

        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());

        //设置确认回调，保障生产端的消息可以正常到达交换机
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            //ack 表示消息是否正常到达交换机
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if (ack){
                    //消息到达交换机
                    System.out.println("消息到达交换机了...");
                }else{
                    //当消息到达交换机失败后，会将我们自己发送的原始消息进行封装到CorrelationData对象

                    ReturnedMessage returned = correlationData.getReturned();
                    Message message = returned.getMessage();
                    //获取消息的唯一性标识
                    String messageId = message.getMessageProperties().getMessageId();
                    //失败了（实时性要求高的，重试--是否可以无限重试？？？ - 重试2-3次 - redis：incr）
                    System.out.println(messageId + " - 消息未到达交换机了...");
                    rabbitTemplate.send(returned.getExchange(),returned.getRoutingKey(),returned.getMessage());
                }
            }
        });

        //设置返回回调，保障生产端的消息可以正常到达队列
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            //当消息到达队列失败后，会触发
            @Override
            public void returnedMessage(ReturnedMessage returned) {
                Message message = returned.getMessage();
                String messageId = message.getMessageProperties().getMessageId();
                System.out.println(messageId + " - 消息未到达队列了...");

                //实时性要求高的，重试--是否可以无限重试？？？ - 重试2-3次 - redis：incr
                rabbitTemplate.send(returned.getExchange(),"boot.topic.xxx.yyy",returned.getMessage());
            }
        });

        return rabbitTemplate;
    }
}
